package com.ruoyi.mall.service.impl;

import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.PrimaryKeyIdUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.customer.api.RemoteCustomerService;
import com.ruoyi.mall.api.domian.AttributeValue;
import com.ruoyi.mall.api.domian.Product;
import com.ruoyi.mall.domain.*;
import com.ruoyi.mall.enums.OrderStatusEnum;
import com.ruoyi.mall.enums.PaymentStatusENum;
import com.ruoyi.mall.enums.ShippingMethodEnum;
import com.ruoyi.mall.mapper.*;
import com.ruoyi.mall.mq.SendService;
import com.ruoyi.mall.service.IOrdersService;
import com.ruoyi.mall.wxpay.WXPayService;
import com.ruoyi.mall.wxpay.vo.WXPayOrderReqVO;
import com.ruoyi.mall.wxpay.vo.WxPayRespVO;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.ShippingAddress;
import com.ruoyi.system.api.domain.SysDept;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author luogongquan
 * @date 2024-10-16
 */
@Slf4j
@Service
public class OrdersServiceImpl implements IOrdersService {
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderCartMapper orderCartMapper;

    @Autowired
    private RemoteCustomerService remoteCustomerService;

    @Autowired
    private PaymentMapper paymentMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private OrderProductAssociationMapper orderProductAssociationMapper;
    @Autowired
    private SendService sendService;
    @Autowired
    private WXPayService wxPayService;

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private AttributeValueMapper attributeValueMapper;


    /**
     * 查询订单
     *
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public Orders selectOrdersById(Long id) {
        return ordersMapper.selectOrdersById(id);
    }

    /**
     * 查询订单列表
     *
     * @param orders 订单
     * @return 订单
     */
    @Override
    public List<Orders> selectOrdersList(Orders orders) {
        return ordersMapper.selectOrdersList(orders);
    }

    /**
     * 新增订单
     *
     * @param orders 订单
     * @return 结果
     */
    @Override
    public int insertOrders(Orders orders) {
        orders.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        orders.setCreateTime(DateUtils.getNowDate());
        return ordersMapper.insertOrders(orders);
    }

    @Override
    @Transactional
    public int insertOrders(OrderVo vo) {
        //查询是否已经存在该订单
        if (ordersMapper.selectOrdersById(vo.getOrderId()) != null) {
            throw new ServiceException("不要重复提交订单！");
        }
        //购买商品信息
        Date nowDate = DateUtils.getNowDate();
        //获取商品金额
        BigDecimal bigDecimal = new BigDecimal(0);
        //单个商品（不从购物车确认订单）生成
        if (vo.getProductId() != null) {
            Long productId = vo.getProductId();
            int num = vo.getNum();
            Product product = productMapper.selectProductById(productId);
            if (product == null) {
                throw new ServiceException("已不存在该商品！");
            }
            bigDecimal = product.getPrice().multiply(BigDecimal.valueOf(num));
            Orders order = createOrder(vo, bigDecimal, nowDate);
            //订单-商品关联表
            OrderProductAssociation association = new OrderProductAssociation();
            association.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
            association.setNum(num);
            association.setPrice(product.getPrice());
            association.setActualPrice(product.getPrice());
            association.setCreateTime(nowDate);
            association.setProductId(productId);
            association.setOrderId(order.getId());
            association.setCreateBy(SecurityUtils.getUsername());
            orderProductAssociationMapper.insertOrderProductAssociation(association);
        } else if (CollectionUtils.isNotEmpty(vo.getOrderCartIds())) {     //购物车购买进入生成订单
            List<Long> orderCartIds = vo.getOrderCartIds();
            Long[] array = orderCartIds.toArray(new Long[0]);
            List<OrderCart> orderCarts = orderCartMapper.selectOrderCartByIds(array);
            if (orderCarts.isEmpty()) {
                throw new ServiceException("购物车已不存在该商品！");
            }
            for (OrderCart orderCart : orderCarts) {
                bigDecimal = orderCart.getPrice().multiply(BigDecimal.valueOf(orderCart.getNum())).add(bigDecimal);
            }
            Orders order = createOrder(vo, bigDecimal, nowDate);
            //订单-商品关联表
            List<OrderProductAssociation> associations = orderCarts.stream().map(cart -> {
                OrderProductAssociation association = new OrderProductAssociation();
                association.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
                association.setNum(cart.getNum());
                association.setPrice(cart.getPrice());
                association.setActualPrice(cart.getPrice());
                association.setCreateTime(nowDate);
                association.setCreateBy(SecurityUtils.getUsername());
                association.setProductId(cart.getProductId());
                association.setOrderId(order.getId());
                return association;
            }).collect(Collectors.toList());
            orderProductAssociationMapper.batchInsertOrderProductAssociation(associations);
            //删除购物车信息
            orderCartMapper.deleteOrderCartByIds(array);
        } else {
            throw new ServiceException("订单提交参数错误！");
        }
        //发送mq信息
        try {
            sendService.sendOrderMessage(vo.getOrderId());
            //微信支付预下单
          /*  WXPayOrderReqVO reqVO = new WXPayOrderReqVO();
            reqVO.setOrderType("1");
            reqVO.setOrderSn(vo.getOrderId());
            reqVO.setOpenId(SecurityUtils.getLoginUser().getOpenId());
            reqVO.setTotalPrice(new BigDecimal(100).multiply(bigDecimal).intValue());
            reqVO.setGoodsName("鹿鸣健康商品");
            WxPayRespVO order = wxPayService.createOrder(reqVO);*/
        } catch (UnsupportedEncodingException e) {
            log.error("订单号：{}mq消息发送失败", vo.getOrderId());
        } catch (Exception e) {
            throw new ServiceException("微信预支付失败");
        }
        return 1;
    }


    private Orders createOrder(OrderVo vo,BigDecimal bigDecimal, Date nowDate) {

        Orders orders = new Orders();
        orders.setId(vo.getOrderId());
        orders.setCreateTime(nowDate);
        orders.setStatus(OrderStatusEnum.PENDING_PAYMENT.getCode());
        orders.setFreightAmount(new BigDecimal(0));
        orders.setPromotionAmount(new BigDecimal(0));
        orders.setOrderDate(nowDate);
        orders.setShippingMethod(vo.getShippingMethod());
        if(ShippingMethodEnum.MAIL.getCode().equals(vo.getShippingMethod())||ShippingMethodEnum.HOME_DELIVERY.getCode().equals(vo.getShippingMethod())){
            //收货地址
            R<ShippingAddress> result = remoteCustomerService.getAddressInfo(vo.getAddressId(), SecurityConstants.INNER);
            ShippingAddress address = result.getData();
            if (!Constants.SUCCESS.equals(result.getCode())) {
                throw new ServiceException("获取收货地址失败！");
            }
            if (result.getData() == null) {
                throw new ServiceException("不存在的收货地址！");
            }

            orders.setReceiverName(address.getName());
            orders.setReceiverPhone(address.getPhone());
            orders.setReceiverProvince(address.getProvince());
            orders.setReceiverProvinceName(address.getProvinceName());
            orders.setReceiverCity(address.getCity());
            orders.setReceiverCityName(address.getCityName());
            orders.setReceiverRegion(address.getRegion());
            orders.setReceiverRegionName(address.getRegionName());
            orders.setReceiverAddress(address.getAddress());
            orders.setDeptId(vo.getDeptId());
        } else if (ShippingMethodEnum.IN_STORE.getCode().equals(vo.getShippingMethod())) {
            orders.setDeptId(vo.getDeptId());
        }
        orders.setCreateBy(SecurityUtils.getUsername());
        orders.setCustomerId(SecurityUtils.getUserId());

        //总金额
        orders.setAmount(bigDecimal);
        //支付金额，暂时还没有优惠券
        orders.setPayAmount(bigDecimal);
        try {
            int i = ordersMapper.insertOrders(orders);
            if (i == 0) {
                throw new ServiceException("提交订单失败！");
            }
        } catch (Exception e) {
            throw new ServiceException("不能重复提交订单！");
        }
        //生成支付订单
        Payment payment = new Payment();
        payment.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        payment.setOrderId(orders.getId());
        payment.setPaymentStatus(PaymentStatusENum.PENDING_PAYMENT.getCode());
        payment.setCreateTime(nowDate);
        payment.setCreateBy(SecurityUtils.getUsername());
        payment.setAmount(bigDecimal);
        paymentMapper.insertPayment(payment);
        return orders;
    }

    /**
     * 取消订单
     *
     * @param id 订单id
     * @return
     */
    @Override
    public int cancelOrder(Long id) {
        Orders orders = new Orders();
        orders.setStatus(OrderStatusEnum.CANCELED.getCode());
        orders.setId(id);
        orders.setUpdateTime(DateUtils.getNowDate());
        orders.setUpdateBy(SecurityUtils.getUsername());
        return ordersMapper.cancelOrder(orders);
    }

    @Override
    public List<Product> getOrderProduct(Long id) {
        return productMapper.getOrderProductByOrderId(id);
    }

    @Override
    public List<Orders> getWxOrderProduct(Orders orders) {
        orders.setCustomerId(SecurityUtils.getUserId());
        List<Orders> ordersList = selectOrdersList(orders);
        if (ordersList.isEmpty()) {
            return Collections.emptyList();
        }
        List<Long> orderIds = ordersList.stream().map(Orders::getId).collect(Collectors.toList());
        List<Product> orderProductByOrderIds = productMapper.getOrderProductByOrderIds(orderIds);
        Map<Long, List<Product>> productMap = orderProductByOrderIds.stream()
                .collect(Collectors.groupingBy(Product::getOrderId));
        ordersList.forEach(order -> order.setProductList(productMap.get(order.getId())));
        return ordersList;
    }

    @Override
    public OrderDetail getOrderDetail(Long orderId) {
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(orderId);
        Orders orders = ordersMapper.selectOrdersById(orderId);
        orderDetail.setStatus(orders.getStatus());
        orderDetail.setOrderDate(orders.getOrderDate());
        orderDetail.setPayAmount(orders.getPayAmount());
        orderDetail.setShipmentsDate(orders.getShipmentsDate());
        orderDetail.setPaymentDate(orders.getPaymentDate());
        orderDetail.setShippingMethod(orders.getShippingMethod());
        if(ShippingMethodEnum.IN_STORE.getCode().equals(orders.getShippingMethod())||ShippingMethodEnum.HOME_DELIVERY.getCode().equals(orders.getShippingMethod())){
            R<SysDept> deptInfo = remoteUserService.getDeptInfo(orders.getDeptId(), SecurityConstants.INNER);
            if(!Constants.SUCCESS.equals(deptInfo.getCode())){
                throw new ServiceException("获取站点失败！");
            }
            SysDept data = deptInfo.getData();
            orderDetail.setDeptName(data.getDeptName());
        }
        if(ShippingMethodEnum.MAIL.getCode().equals(orders.getShippingMethod())||ShippingMethodEnum.HOME_DELIVERY.getCode().equals(orders.getShippingMethod())){
            orderDetail.setReceiverName(orders.getReceiverName());
            orderDetail.setReceiverAddress(orders.getReceiverAddress());
            orderDetail.setReceiverCity(orders.getReceiverCity());
            orderDetail.setReceiverCityName(orders.getReceiverCityName());
            orderDetail.setReceiverProvince(orders.getReceiverProvince());
            orderDetail.setReceiverProvinceName(orders.getReceiverProvinceName());
            orderDetail.setReceiverRegion(orders.getReceiverRegion());
            orderDetail.setReceiverRegionName(orders.getReceiverRegionName());
            orderDetail.setReceiverPhone(orders.getReceiverPhone());
            orderDetail.setReceiverAddress(orders.getReceiverAddress());
        }
        List<Product> productList = productMapper.getOrderProductByOrderIds(Collections.singletonList(orderId));
        List<Long> productIds = productList.stream().map(Product::getId).collect(Collectors.toList());
        List<AttributeValue> attributeValues = attributeValueMapper.selectAttributeValueByProductIds(productIds);
        Map<Long, List<AttributeValue>> collect = attributeValues.stream().collect(Collectors.groupingBy(AttributeValue::getProductId));
        productList.forEach(product -> {
            List<AttributeValue> attr = collect.get(product.getId());
            if(attr!=null){
                String attyValue = attr.get(0).getAttyValue();
                product.setSpecifications(attyValue);

            }

        });
        orderDetail.setProductList(productList);
        return orderDetail;
    }

    /**
     * 修改订单
     *
     * @param orders 订单
     * @return 结果
     */
    @Override
    public int updateOrders(Orders orders) {
        orders.setUpdateTime(DateUtils.getNowDate());
        return ordersMapper.updateOrders(orders);
    }

    /**
     * 批量删除订单
     *
     * @param ids 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteOrdersByIds(Long[] ids) {
        return ordersMapper.deleteOrdersByIds(ids);
    }

    /**
     * 删除订单信息
     *
     * @param id 订单主键
     * @return 结果
     */
    @Override
    public int deleteOrdersById(Long id) {
        return ordersMapper.deleteOrdersById(id);
    }
}
